package org.voidness.oje2d.gui.docks;

import org.voidness.oje2d.Engine;
import org.voidness.oje2d.GLColor;
import org.voidness.oje2d.GLImage;
import org.voidness.oje2d.gui.Widget;
import org.voidness.oje2d.gui.Window;

public class DockedWindow extends Window {
    public static final int LEFT = 0;

    public static final int TOP = 1;

    public static final int RIGHT = 2;

    public static final int BOTTOM = 3;

    private Window window = null;

    private DockEdge edge = null;

    private boolean docked;

    private boolean extended;

    private boolean docking;

    private boolean moving;

    private GLColor windowColor = null;

    private GLColor edgeColor = null;

    private int type;

    public DockedWindow(int mWidth, int mHeight, int mType) {
        super(mWidth, mHeight);
        type = mType;
        initializeBehaviour(mWidth, mHeight);
        init();
    }

    public DockedWindow(int xPos, int yPos, int mWidth, int mHeight, int mType) {
        super(xPos, yPos, mWidth, mHeight);
        type = mType;
        initializeBehaviour(xPos, yPos, mWidth, mHeight);
        init();
    }

    public void add(Widget mWidget) {
        mWidget.setParent(window);
        window.add(mWidget);
    }

    public boolean isExtended() {
        return extended;
    }

    private void initializeBehaviour(int mWidth, int mHeight) {
        switch (type) {
        case LEFT: {
            // The center of the display window
            int xPos = 0;
            int yPos = Engine.getInstance().getDisplayBounds().getY() / 2;

            // Align the window so it's center is in the center of the display
            // And left docked (outside the screen)
            xPos -= mWidth;
            yPos -= mHeight / 2;

            // Main window
            window = new Window(xPos, yPos, mWidth, mHeight);

            // Edge window
            edge = new VerticalDockEdge(-1, yPos, 10, mHeight);
        }
            break;

        case TOP: {

        }
            break;

        case RIGHT: {

        }
            break;

        case BOTTOM: {

        }
            break;
        }
    }

    private void initializeBehaviour(int xPos, int yPos, int mWidth, int mHeight) {
        switch (type) {
        case LEFT: {
            // Main window
            window = new Window(-mWidth, yPos, mWidth, mHeight);

            // Edge window
            edge = new VerticalDockEdge(-1, yPos, 10, mHeight);
        }
            break;

        case TOP: {
            // Main window
            window = new Window(xPos, -mHeight, mWidth, mHeight);

            // Edge window
            edge = new HorizontalDockEdge(xPos, -1, mWidth, 10);
        }
            break;

        case RIGHT: {
            // VerticalDockEdge edgeImp = (VerticalDockEdge) edge;

            // Main window
            window =
                    new Window(Engine.getInstance().getDisplayBounds().getX(),
                            yPos, mWidth, mHeight);

            // Edge window
            edge =
                    new VerticalDockEdge(Engine.getInstance()
                            .getDisplayBounds().getX() - 10 + 1, yPos, 10,
                            mHeight);
        }
            break;

        case BOTTOM: {
            // Main window
            window =
                    new Window(xPos, Engine.getInstance().getDisplayBounds()
                            .getY(), mWidth, mHeight);

            // Edge window
            edge =
                    new HorizontalDockEdge(xPos, Engine.getInstance()
                            .getDisplayBounds().getY() - 10 + 1, mWidth, 10);
        }
            break;
        }
    }

    private void init() {
        window.setFixed(true);
        window.setColor(GLColor.WHITE);

        docked = true;
        docking = false;

        windowColor = GLColor.WHITE;// GLColor.randomColor(0.3f);
        edgeColor = GLColor.WHITE;// GLColor.randomColor(0.3f);
    }

    // Required to pass events to window
    public void keyPressed(int mKey, char mChar) {
        window.keyPressed(mKey, mChar);
    }

    // Required to pass events to window
    public void keyReleased(int mKey) {
        window.keyReleased(mKey);
    }

    public void setBodyImage(GLImage mImage) {
        window.setImage(mImage);
    }

    public void setEdgeImages(GLImage[] mEdges, String mBack) {
        edge.setImages(mEdges, mBack);
    }

    public void updatePosition() {
        super.updatePosition();

        switch (type) {
        case LEFT:
            updateLeft();
            break;
        case TOP:
            updateTop();
            break;
        case RIGHT:
            updateRight();
            break;
        case BOTTOM:
            updateBottom();
            break;
        }
    }

    public void updateLeft() {
        VerticalDockEdge edgeImp = (VerticalDockEdge) edge;

        // It's docking
        if (docking && moving) {
            // Decrement position
            xPos--;
            window.setXPos(window.getXPos() - 1);
            edgeImp.setXPos(edgeImp.getXPos() - 1);

            // Check if we reached the dock
            if (edgeImp.getXPos() == -1) {
                // It's docked
                docked = true;

                // Not docking anymore
                docking = false;

                // And also not moving
                moving = false;
            }
        }
        // It's extending
        else if (!docking && moving) {
            // Increment position
            xPos++;
            window.setXPos(window.getXPos() + 1);
            edgeImp.setXPos(edgeImp.getXPos() + 1);

            // Check for full extendness
            if (window.getXPos() == -1) {
                extended = true;
                docking = true;
                moving = false;
            }
        }

        // If the mouse is not there and the window is not docked, let's dock it
        if (!edgeImp.hasMouseOver() && !window.hasMouseOver() && !docked)
            docking = true;

        // If the mouse is not there, but it's docking OR
        // if the mouse is there, and the window is docked and extending THEN
        // set the window as moving and set it as not docked or extended
        if ((!edgeImp.hasMouseOver() && !window.hasMouseOver() && docking)
                || ((edgeImp.hasMouseOver() || window.hasMouseOver()) && docked && !docking)) {
            moving = true;
            docked = false;
            extended = false;
        }
    }

    public void updateTop() {
        HorizontalDockEdge edgeImp = (HorizontalDockEdge) edge;

        // It's docking
        if (docking && moving) {
            // Decrement position
            yPos--;
            window.setYPos(window.getYPos() - 1);
            edgeImp.setYPos(edgeImp.getYPos() - 1);

            // Check if we reached the dock
            if (edgeImp.getYPos() == 0) {
                // It's docked
                docked = true;

                // Not docking anymore
                docking = false;

                // And also not moving
                moving = false;
            }
        }
        // It's extending
        else if (!docking && moving) {
            // Increment position
            yPos++;
            window.setYPos(window.getYPos() + 1);
            edgeImp.setYPos(edgeImp.getYPos() + 1);

            // Check for full extendness
            if (edgeImp.getYPos() == window.getHeight() - 2) {
                extended = true;
                docking = true;
                moving = false;
            }
        }

        // If the mouse is not there and the window is not docked, let's dock it
        if (!edgeImp.hasMouseOver() && !window.hasMouseOver() && !docked)
            docking = true;

        // If the mouse is not there, but it's docking OR
        // if the mouse is there, and the window is docked and extending THEN
        // set the window as moving and set it as not docked or extended
        if ((!edgeImp.hasMouseOver() && !window.hasMouseOver() && docking)
                || ((edgeImp.hasMouseOver() || window.hasMouseOver()) && docked && !docking)) {
            moving = true;
            docked = false;
            extended = false;
        }
    }

    public void updateRight() {
        VerticalDockEdge edgeImp = (VerticalDockEdge) edge;

        // It's docking
        if (docking && moving) {
            // Decrement position
            xPos++;
            window.setXPos(window.getXPos() + 1);
            edgeImp.setXPos(edgeImp.getXPos() + 1);

            // Check if we reached the dock
            if (window.getXPos() == Engine.getInstance().getDisplayBounds()
                    .getX()) {
                // It's docked
                docked = true;

                // Not docking anymore
                docking = false;

                // And also not moving
                moving = false;
            }
        }
        // It's extending
        else if (!docking && moving) {
            // Increment position
            xPos--;
            window.setXPos(window.getXPos() - 1);
            edgeImp.setXPos(edgeImp.getXPos() - 1);

            // Check for full extendness
            if (edgeImp.getXPos() == Engine.getInstance().getDisplayBounds()
                    .getX()
                    - window.getWidth()) {
                extended = true;
                docking = true;
                moving = false;
            }
        }

        // If the mouse is not there and the window is not docked, let's dock it
        if (!edgeImp.hasMouseOver() && !window.hasMouseOver() && !docked)
            docking = true;

        // If the mouse is not there, but it's docking OR
        // if the mouse is there, and the window is docked and extending THEN
        // set the window as moving and set it as not docked or extended
        if ((!edgeImp.hasMouseOver() && !window.hasMouseOver() && docking)
                || ((edgeImp.hasMouseOver() || window.hasMouseOver()) && docked && !docking)) {
            moving = true;
            docked = false;
            extended = false;
        }
    }

    public void updateBottom() {
        HorizontalDockEdge edgeImp = (HorizontalDockEdge) edge;

        // It's docking
        if (docking && moving) {
            // Decrement position
            yPos++;
            window.setYPos(window.getYPos() + 1);
            edgeImp.setYPos(edgeImp.getYPos() + 1);

            // Check if we reached the dock
            if (edgeImp.getYPos() == Engine.getInstance().getDisplayBounds()
                    .getY()
                    - edgeImp.getHeight()) {
                // It's docked
                docked = true;

                // Not docking anymore
                docking = false;

                // And also not moving
                moving = false;
            }
        }
        // It's extending
        else if (!docking && moving) {
            // Increment position
            yPos--;
            window.setYPos(window.getYPos() - 1);
            edgeImp.setYPos(edgeImp.getYPos() - 1);

            // Check for full extendness
            if (window.getYPos() == Engine.getInstance().getDisplayBounds()
                    .getY()
                    - window.getHeight() + 1) {
                extended = true;
                docking = true;
                moving = false;
            }
        }

        // If the mouse is not there and the window is not docked, let's dock it
        if (!edgeImp.hasMouseOver() && !window.hasMouseOver() && !docked)
            docking = true;

        // If the mouse is not there, but it's docking OR
        // if the mouse is there, and the window is docked and extending THEN
        // set the window as moving and set it as not docked or extended
        if ((!edgeImp.hasMouseOver() && !window.hasMouseOver() && docking)
                || ((edgeImp.hasMouseOver() || window.hasMouseOver()) && docked && !docking)) {
            moving = true;
            docked = false;
            extended = false;
        }
    }

    public void draw(GLColor mColor) {
        if (window != null && edge != null) {
            window.draw(windowColor);

            if (edge instanceof VerticalDockEdge)
                ((VerticalDockEdge) edge).draw(edgeColor);
            else
                ((HorizontalDockEdge) edge).draw(edgeColor);
        }

        // Cycle the widget list and draw all
        /*
         * for (int i = 0; i < widgetList.size(); i++) { Widget widget =
         * (Widget) widgetList.elementAt(i); widget.draw(windowColor); }
         */
    }
}